package com.ttk.issuetracker.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.ttk.issuetracker.dao.ProjectDao;
import com.ttk.issuetracker.dao.TaskDao;
import com.ttk.issuetracker.dao.TaskLogDao;
import com.ttk.issuetracker.model.Project;
import com.ttk.issuetracker.model.Task;
import com.ttk.issuetracker.model.User;
import com.ttk.issuetracker.vo.Result;
import com.ttk.issuetracker.vo.ResultFactory;

@Transactional
@Service("taskService")
public class TaskServiceImpl extends AbstractService implements TaskService {

	@Autowired
	private ProjectDao projectDao;
	@Autowired
	private TaskDao taskDao;
	@Autowired
	private TaskLogDao taskLogDao;

	public TaskServiceImpl() {
		super();
	}

	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	@Override
	public Result<Task> store(Integer idTask, Integer idProject,
			String taskName, String actionUsername) {
		User actionUser = userDao.findByUsername(actionUsername);
        if (!actionUser.isAdmin()) {
            return ResultFactory.getFailResult(USER_NOT_ADMIN);
        }

		User user = userDao.findByUsername(actionUsername);
		if (!user.isAdmin()) {
			return ResultFactory.getFailResult(USER_NOT_ADMIN);
		}

		Project p = projectDao.find(idProject);
		if (p == null) {
			return ResultFactory
					.getFailResult("Unable to store task without a valid project [idProject="
							+ idProject + "]");
		}

		Task task;
		if (idTask == null) {
			task = new Task();
			task.setProject(p);
			p.getTasks().add(task);
		} else {
			task = taskDao.find(idTask);
			if (task == null) {
				return ResultFactory
						.getFailResult("Unable to find task instance with idTask="
								+ idTask);
			} else {
				if (!task.getProject().equals(p)) {
					Project currentProject = task.getProject();
					task.setProject(p);
					p.getTasks().add(task);
					currentProject.getTasks().remove(task);
				}
			}
		}

		task.setTaskName(taskName);

		if (task.getId() == null) {
			taskDao.persist(task);
		} else {
			taskDao.merge(task);
		}

		return ResultFactory.getSuccessResult(task);
	}

	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	@Override
	public Result<Task> remove(Integer idTask, String actionUsername) {
		User actionUser = userDao.findByUsername(actionUsername);
        if (!actionUser.isAdmin()) {
            return ResultFactory.getFailResult(USER_NOT_ADMIN);
        }
		if(idTask == null) {
			return ResultFactory.getFailResult("Unable find task with null primary key");
		}
		
		Task task = taskDao.find(idTask);
		long taskLogCount = taskLogDao.findTaskLogCountByTask(task);
		if(task == null) {
			return ResultFactory.getFailResult("Unable to load Task for removal with idTask=" + idTask);
		} else if(taskLogCount > 0) {
			return ResultFactory.getFailResult("Cannot remove task that has task log assigned");
		} else {
			Project p = task.getProject();
			taskDao.remove(task);
			if(p != null) {
				p.getTasks().remove(task);
			}
			
			String msg = "Task " + task.getTaskName() + " was deleted by " + actionUsername;
			logger.info(msg);
			return ResultFactory.getSuccessResultMsg(msg);
		}
	}

	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	@Override
	public Result<Task> find(Integer idTask, String actionUsername) {
		if (isValidUser(actionUsername)) {
			Task task = taskDao.find(idTask);
			return ResultFactory.getSuccessResult(task);
		} else {
			return ResultFactory.getFailResult(USER_INVALID);
		}
	}

	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	@Override
	public Result<List<Task>> findAll(String actionUsername) {
		if (isValidUser(actionUsername)) {
			return ResultFactory.getSuccessResult(taskDao.findAll());
		} else {
			return ResultFactory.getFailResult(USER_INVALID);
		}
	}

}
